package com.prodog.usermodule.role.service.impl;

import com.prodog.command.annonations.Service;
import com.prodog.command.entity.CommandResult;
import com.prodog.command.entity.GameCommand;
import com.prodog.command.entity.RoleGameCommand;
import com.prodog.commonmodule.prop.caculate.factory.ObjPropHandlerFactory;
import com.prodog.database.wrapper.DataWrapperCentral;
import com.prodog.gamemodule.config.BirthConfig;
import com.prodog.gamemodule.config.ServerConfig;
import com.prodog.gamemodule.gameworld.map.wrapper.GameMapWrapper;
import com.prodog.gamemodule.profession.entity.Profession;
import com.prodog.gamemodule.profession.wrapper.ProfessionWrapper;
import com.prodog.usermodule.role.entity.RoleBag;
import com.prodog.usermodule.role.entity.RoleInfo;
import com.prodog.usermodule.role.entity.RoleProp;
import com.prodog.usermodule.role.service.RoleInfoService;
import com.prodog.usermodule.role.vo.RoleInfoVo;
import com.prodog.usermodule.role.vo.RoleListVo;
import com.prodog.usermodule.role.vo.convetor.RoleInfoVoConvetor;
import com.prodog.usermodule.role.wrapper.RoleBagWrapper;
import com.prodog.usermodule.role.wrapper.RoleInfoWrapper;
import com.prodog.usermodule.role.wrapper.RolePropWrapper;
import com.prodog.usermodule.user.dtos.CreateRoleDTO;
import com.prodog.usermodule.user.entity.UserInfo;
import com.prodog.usermodule.user.wrapper.UserInfoWrapper;
import com.prodog.util.MsgTemplateUtil;
import com.prodog.utils.RandomUtil;
import com.prodog.utils.bean.BeanUtil;
import lombok.RequiredArgsConstructor;

import java.util.*;
import java.util.concurrent.locks.ReentrantLock;

@Service
@RequiredArgsConstructor
public class RoleInfoServiceImpl implements RoleInfoService {
    /****************数据源********************/
    private final UserInfoWrapper userInfoWrapper;
    private final RoleInfoWrapper roleInfoWrapper;
    private final RolePropWrapper rolePropWrapper;
    private final RoleBagWrapper roleBagWrapper;
    private final GameMapWrapper gameMapWrapper;
    private final ProfessionWrapper professionWrapper;

    /****************【配置】******************/
    private final BirthConfig birthConfig;
    private final ServerConfig serverConfig;

    /****************【锁】******************/
    private ReentrantLock createRoleLock = new ReentrantLock();


    @Override
    public CommandResult createRole(GameCommand command, CreateRoleDTO dto) {
        //查询是否存在账户
        UserInfo userInfo = userInfoWrapper.getById(command.getFromQQ());
        if (userInfo == null) {
            userInfo = new UserInfo() {{
                setId(command.getFromQQ());
                setRegistTime(new Date());
                setCopoun(birthConfig.getCopoun());
            }};
        }
        //查询账户存在的角色数量
        long roleCount = roleInfoWrapper.countByColumn("userId", userInfo.getId());
        if (roleCount >= serverConfig.getRoleLimit()) {
            return CommandResult.failure("创建失败，一个账户最多可创建" + serverConfig.getRoleLimit() + "个角色！");
        } else if (roleInfoWrapper.countByColumn("roleName", dto.getRoleName()) > 0) {
            return CommandResult.failure("创建失败，已存在相同角色名的玩家角色");
        } else {
            createRoleLock.lock();
            RoleInfo roleInfo;
            RoleProp roleProp;
            try {
                //创建角色信息 角色属性 角色背包
                long maxSerialNum = roleInfoWrapper.max("serialNum");
                String roleId = command.getFromQQ() + "-" + (maxSerialNum + 1);
                roleInfo = new RoleInfo() {{
                    setId(roleId);
                    setUserId(command.getFromQQ());
                    setSerialNum(maxSerialNum + 1);
                    setRoleName(dto.getRoleName());
                    setSex(dto.getSex());
                    setMapId(birthConfig.getBirthMap());
                    setMoney(birthConfig.getMoney());
                    setTitle(birthConfig.getBirthTitle());
                }};

                roleProp = RandomUtil.randomByMap(birthConfig.getBirthProp(), RoleProp.class);
                roleProp.setId(roleId);

                RoleBag roleBag = new RoleBag() {{
                    setId(roleId);
                    setItemNums(birthConfig.getBagItemNums());
                    setItems(new ArrayList<>());
                }};
                roleInfoWrapper.save(roleInfo);
                rolePropWrapper.save(roleProp);
                roleBagWrapper.save(roleBag);

                //切换角色
                userInfo.setRoleId(roleId);
                userInfoWrapper.save(userInfo);
            } finally {
                createRoleLock.unlock();
            }

            Map fmtData = new HashMap();
            fmtData.putAll(BeanUtil.beanToMap(roleProp));
            fmtData.put("roleName", roleInfo.getRoleName());
            fmtData.put("mapName", gameMapWrapper.getById(roleInfo.getMapId()).getName());
            return CommandResult.success(MsgTemplateUtil.formatMsg("游戏配置/消息模板/创建角色成功.txt", fmtData));
        }
    }

    @Override
    public CommandResult changeRole(GameCommand command, String roleName) {
        //获取当前角色对应要切换的角色名
        UserInfo info = userInfoWrapper.getById(command.getFromQQ());
        RoleInfo curRole = roleInfoWrapper.getById(info.getRoleId());
        if (curRole.getRoleName().equals(roleName)) {
            return CommandResult.failure("你正在使用该角色，无需切换。");
        }
        //获取当前用户id和切换角色名的角色
        RoleInfo changeRoleInfo = roleInfoWrapper.getByColumns("userId", info.getId(), "roleName", roleName);
        if (changeRoleInfo == null) {
            return CommandResult.failure("切换失败，你的账户里没有该角色。");
        }
        //切换角色
        RoleProp changeRoleProp = rolePropWrapper.getById(changeRoleInfo.getId());
        info.setRoleId(changeRoleInfo.getId());
        //切换到要删除的角色则取消删除
        info.setDelRoleId(changeRoleInfo.getId().equals(info.getDelRoleId()) ? null : info.getDelRoleId());
        userInfoWrapper.save(info);
        return CommandResult.success("切换成功！当前角色：[" + changeRoleProp.getLevel() + "级]" + changeRoleInfo.getRoleName());
    }

    @Override
    public CommandResult roleList(GameCommand command) {
        //获取当前用户的角色信息 拼成角色列表VO
        List<RoleInfo> roleInfoList = roleInfoWrapper.listByColumn("userId", command.getFromQQ());
        List<RoleListVo> listVos = new ArrayList<>();
        for (RoleInfo roleInfo : roleInfoList) {
            RoleListVo vo = new RoleListVo() {{
                setRoleName(roleInfo.getRoleName());
                setLevel(rolePropWrapper.getById(roleInfo.getId()).getLevel());
                if (roleInfo.getId().equals(userInfoWrapper.getById(command.getFromQQ()).getRoleId())) {
                    setUsing(true);
                }
            }};
            listVos.add(vo);
        }
        return CommandResult.success(MsgTemplateUtil.formatMsg("游戏配置/消息模板/角色列表.txt", new HashMap() {{
            put("roleList", listVos);
        }}));
    }

    @Override
    public CommandResult roleInfo(GameCommand command) {
        UserInfo userInfo = userInfoWrapper.getById(command.getFromQQ());
        RoleInfo roleInfo = roleInfoWrapper.getById(userInfo.getRoleId());
        RoleInfoVo vo = new RoleInfoVoConvetor().convert(roleInfo);
        //返回模板消息
        return CommandResult.success(MsgTemplateUtil.formatMsg("游戏配置/消息模板/角色信息.txt", new HashMap() {{
            put("roleInfo", vo);
        }}));
    }

    @Override
    public CommandResult deleteRole(GameCommand command, String roleName) {
        //获取当前操作角色
        UserInfo info = userInfoWrapper.getById(command.getFromQQ());
        RoleInfo curRole = roleInfoWrapper.getById(info.getRoleId());
        if (curRole.getRoleName().equals(roleName)) {
            return CommandResult.failure("您正在使用该角色，无法删除。");
        }
        //获取当前用户id和切换角色名的角色
        RoleInfo deleteRoleInfo = roleInfoWrapper.getByColumns("userId", info.getId(), "roleName", roleName);
        if (deleteRoleInfo == null) {
            return CommandResult.failure("您的账户里没有该角色，无法删除");
        }
        RoleProp deleteRoleProp = rolePropWrapper.getById(deleteRoleInfo.getId());
        info.setDelRoleId(deleteRoleInfo.getId());
        userInfoWrapper.save(info);
        return CommandResult.success(MsgTemplateUtil.formatMsg("游戏配置/消息模板/删除角色.txt", new HashMap() {{
            put("level", deleteRoleProp.getLevel());
            put("roleName", deleteRoleInfo.getRoleName());
        }}));
    }

    @Override
    public CommandResult confirmDelete(GameCommand command) {
        //获取当前要删除的角色
        UserInfo userInfo = userInfoWrapper.getById(command.getFromQQ());
        if (userInfo.getDelRoleId() == null) {
            return CommandResult.failure("您没有需要删除的角色");
        }
        RoleInfo delRoleInfo = roleInfoWrapper.getById(userInfo.getDelRoleId());
        RoleProp delRoleProp = rolePropWrapper.getById(userInfo.getDelRoleId());
        DataWrapperCentral.removeById(userInfo.getDelRoleId());
        //删除角色
        return CommandResult.success(MsgTemplateUtil.formatMsg("游戏配置/消息模板/删除角色成功.txt", new HashMap() {{
            put("level", delRoleProp.getLevel());
            put("roleName", delRoleInfo.getRoleName());
        }}));
    }

    @Override
    public CommandResult cancelDelete(GameCommand command) {
        //获取当前要删除的角色
        UserInfo userInfo = userInfoWrapper.getById(command.getFromQQ());
        if (userInfo.getDelRoleId() == null) {
            return CommandResult.failure("您没有需要删除的角色。");
        }
        userInfo.setDelRoleId(null);
        userInfoWrapper.save(userInfo);
        return CommandResult.success("取消删除成功！");
    }

    @Override
    public CommandResult selectProfession(RoleGameCommand cmd, String professionName) {
        //判断是否已有职业 是否初始职业
        if (cmd.getRoleInfo().getProfessionId() != null) {
            return CommandResult.failure(MsgTemplateUtil.formatMsg("游戏配置/消息模板/选择职业_已有职业.txt", new HashMap() {{
                put("roleInfo", cmd.getRoleInfo());
            }}));
        }
        Profession profession = professionWrapper.getByColumn("professionName", professionName);
        if (profession == null) {
            return CommandResult.failure(MsgTemplateUtil.formatMsg("游戏配置/消息模板/选择职业_职业不存在.txt", new HashMap() {{
                put("roleInfo", cmd.getRoleInfo());
            }}));
        }
        if (!profession.isInitial()) {
            return CommandResult.failure(MsgTemplateUtil.formatMsg("游戏配置/消息模板/选择职业_非初始职业.txt", new HashMap() {{
                put("roleInfo", cmd.getRoleInfo());
            }}));
        }
        cmd.getRoleInfo().setProfessionId(profession.getId());
        roleInfoWrapper.save(cmd.getRoleInfo());
        //选择职业保存
        return CommandResult.success(MsgTemplateUtil.formatMsg("游戏配置/消息模板/选择职业_选择成功.txt", new HashMap() {{
            put("roleInfo", cmd.getRoleInfo());
            put("profession", profession);
        }}));
    }

    @Override
    public CommandResult roleProp(RoleGameCommand cmd) {
        //获取角色属性 计算
        RoleProp prop = rolePropWrapper.getById(cmd.getRoleId());
        prop = (RoleProp) new ObjPropHandlerFactory().getHandler(RoleProp.class, new HashMap() {{
            put(ObjPropHandlerFactory.KEY_ROLE_INFO, cmd.getRoleInfo());
        }}).handle(prop);
        Profession profession = professionWrapper.getById(cmd.getRoleInfo().getProfessionId());
        RoleProp finalProp = prop;

        return CommandResult.success(MsgTemplateUtil.formatMsg("游戏配置/消息模板/角色属性.txt", new HashMap() {{
            put("professionName", profession == null ? "无" : profession.getProfessionName());
            put("roleInfo", cmd.getRoleInfo());
            put("roleProp", finalProp);
        }}));
    }
}
